package com.xing.retry;

import com.github.rholder.retry.*;
import com.google.common.base.Predicates;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.SocketTimeoutException;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Author: linjx
 * Date: 2018/9/25
 */
public class RpcRetryUtil {

    private static Logger logger = LoggerFactory.getLogger(RpcRetryUtil.class);

    private static final ExecutorService extutor = RpcThreadPoolConfig.executor();

    /**
     * 需要重试的方法返回值boolean类型,为true则重试
     * 存在SocketTimeoutException读超时则重试
     * 默认重试三次，重试间隔150ms
     * @return
     */
    private static Retryer DEFALUT_RETRYER = RetryerBuilder.<Boolean>newBuilder()
                .retryIfResult(Predicates.equalTo(true))
                .retryIfExceptionOfType(SocketTimeoutException.class)
                .withStopStrategy(StopStrategies.stopAfterAttempt(3))
                .withWaitStrategy(WaitStrategies.fixedWait(150, TimeUnit.MILLISECONDS))
                .build();

    public static void asyncRetryDefault(Callable callable){
        Objects.requireNonNull(callable);
        extutor.execute(() -> {
            try {
                DEFALUT_RETRYER.call(callable);
            } catch (ExecutionException | RetryException e) {
                logger.error("重试失败异常：" + e.getMessage(), e);
            } catch (Throwable throwable) {
                //其他异常
                logger.error(throwable.getMessage(), throwable);
            }
        });
    }

    public static void asyncRetry(Retryer retryer, Callable callable){
        Objects.requireNonNull(retryer);
        Objects.requireNonNull(callable);
        extutor.execute(() -> {
            try {
                retryer.call(callable);
            } catch (ExecutionException | RetryException e) {
                logger.error("重试失败异常：" + e.getMessage(), e);
            } catch (Throwable throwable) {
                //其他异常
                logger.error(throwable.getMessage(), throwable);
            }
        });
    }
}
